package com.presto.directo.mvvm.view

import android.Manifest
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.MediaStore
import android.view.Gravity
import android.view.View
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.FileProvider
import androidx.core.view.isVisible
import androidx.core.widget.doOnTextChanged
import com.bumptech.glide.Glide
import com.presto.directo.base.BaseActivity
import com.presto.directo.databinding.ActivityPersoninfoBinding
import com.presto.directo.databinding.DialogSelectPhotoBinding
import com.presto.directo.mvvm.viewmodel.*
import com.presto.directo.net.getHttpMap
import com.presto.directo.net.sign
import com.presto.directo.utils.*
import com.tbruyelle.rxpermissions3.RxPermissions
import kotlinx.coroutines.rx3.awaitFirst
import ru.whalemare.sheetmenu.SheetMenu
import java.io.File
import java.io.FileOutputStream

class InfoPersonActivity : BaseActivity() {
    override val rootView: View
        get() = binding.root

    private val views by lazy {
        arrayListOf(
            binding.etIdNum,
            binding.etFatherName,
            binding.etMotherName,
            binding.etFirstName,
            binding.etRfcStart,
            binding.etRfcEnd
        )
    }
    private val binding by lazy { ActivityPersoninfoBinding.inflate(layoutInflater) }
    private val viewModel: InfoViewModel by lazy { getViewModel() }

    private val launchFrontByCamera = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
        if (it.resultCode != RESULT_OK) return@registerForActivityResult
        viewModel.compressor(
            this,
            PhotoType.FRONT,
            binding.etIdNum.text.isNullOrBlank() || binding.etFatherName.text.isNullOrBlank() || binding.etMotherName.text.isNullOrBlank() || binding.etFirstName.text.isNullOrBlank()
        )
    }
    private val launchReverseByCamera = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
        if (it.resultCode != RESULT_OK) return@registerForActivityResult
        viewModel.compressor(this, PhotoType.REVERSE)
    }
    private val launchSelf = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
        if (it.resultCode != RESULT_OK) return@registerForActivityResult
        viewModel.compressor(this, PhotoType.LIVE)
    }

    private val launchFrontByGallery = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
        if (it.resultCode != RESULT_OK) return@registerForActivityResult
        val uri = it.data?.data ?: return@registerForActivityResult
        val bytes = contentResolver.openInputStream(uri)?.readBytes()
        val path = externalCacheDir?.path + File.separator + System.currentTimeMillis() + ".jpg"
        val outputStream = FileOutputStream(File(path))
        outputStream.write(bytes)
        viewModel.frontPath = path
        viewModel.compressor(
            this,
            PhotoType.FRONT,
            binding.etIdNum.text.isNullOrBlank() || binding.etFatherName.text.isNullOrBlank() || binding.etMotherName.text.isNullOrBlank() || binding.etFirstName.text.isNullOrBlank()
        )
    }

    private val launchReverseByGallery = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
        if (it.resultCode != RESULT_OK) return@registerForActivityResult
        val uri = it.data?.data ?: return@registerForActivityResult
        val bytes = contentResolver.openInputStream(uri)?.readBytes()
        val path = externalCacheDir?.path + File.separator + System.currentTimeMillis() + ".jpg"
        val outputStream = FileOutputStream(File(path))
        outputStream.write(bytes)
        viewModel.reversePath = path
        viewModel.compressor(this, PhotoType.REVERSE)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Af.show_personInfo_page.track(this)
        viewModel.imgLiveData.observe(this) {
            if (it == PhotoType.FRONT) {
                Glide.with(this).load(viewModel.frontPath).into(binding.ivCard1)
                binding.ivCard1Ok.isVisible = true
            } else if (it == PhotoType.REVERSE) {
                Glide.with(this).load(viewModel.reversePath).into(binding.ivCard2)
                binding.ivCard2Ok.isVisible = true
            } else {
                Glide.with(this).load(viewModel.livingPath).into(binding.ivSelf)
                binding.ivSelfOk.isVisible = true
            }
            updateBtn()
        }
        viewModel.infoLiveData.observe(this) {
            binding.apply {
                ivCard1Ok.isVisible = it.frontId.isNotEmpty()
                ivCard2Ok.isVisible = it.reverseId.isNotEmpty()
                ivSelfOk.isVisible = it.livingId.isNotEmpty()
                etIdNum.setText(it.curp)
                etFatherName.setText(it.father_surname)
                etMotherName.setText(it.mother_surname)
                etFirstName.setText(it.real_name)
                if (it.tax_id.length >= 10) {
                    etRfcStart.text = it.tax_id.substring(0, 10)
                }
                if (it.tax_id.length >= 13) {
                    etRfcEnd.setText(it.tax_id.substring(10, it.tax_id.length))
                }
            }
        }
        viewModel.uploadLiveData.observe(this) {
            Af.success_submit_personInfo.track(this)
            startActivity(Intent(this, CardListActivity::class.java))
            finish()
        }
        viewModel.ocrLiveData.observe(this) {
            if (binding.etIdNum.text.isNullOrBlank()) binding.etIdNum.setText(it.idNumber)
            if (binding.etFatherName.text.isNullOrBlank()) binding.etFatherName.setText(it.fatherLastName)
            if (binding.etMotherName.text.isNullOrBlank()) binding.etMotherName.setText(it.motherLastName)
            if (binding.etFirstName.text.isNullOrBlank()) binding.etFirstName.setText(it.name)
        }
        viewModel.getInfo()
    }

    override fun initEvent() {
        views.forEach {
            it.doOnTextChanged { text, start, before, count ->
                if (it == binding.etIdNum) {
                    if (it.text.length >= 10) {
                        binding.etRfcStart.text = it.text.substring(0, 10)
                    } else {
                        binding.etRfcStart.text = ""
                    }
                    binding.tvTip.isVisible = it.text.length < 18
                }
                updateBtn()
            }
        }
        binding.ivCard1.setOnClickListener {
            showDialog(gravity = Gravity.BOTTOM) { dialog ->
                val binding = DialogSelectPhotoBinding.inflate(layoutInflater)
                dialog.setContentView(binding.root)
                binding.tvCamera.setOnClickListener {
                    dialog.dismiss()
                    takePhoto(launchFrontByCamera)
                }
                binding.tvGallery.setOnClickListener {
                    dialog.dismiss()
                    toGallery(launchFrontByGallery)
                }
                binding.tvCancel.setOnClickListener { dialog.dismiss() }
            }
        }
        binding.ivCard2.setOnClickListener {
            showDialog(gravity = Gravity.BOTTOM) { dialog ->
                val binding = DialogSelectPhotoBinding.inflate(layoutInflater)
                dialog.setContentView(binding.root)
                binding.tvCamera.setOnClickListener {
                    dialog.dismiss()
                    takePhoto(launchReverseByCamera)
                }
                binding.tvGallery.setOnClickListener {
                    dialog.dismiss()
                    toGallery(launchReverseByGallery)
                }
                binding.tvCancel.setOnClickListener { dialog.dismiss() }
            }
        }
        binding.ivSelf.setOnClickListener {
            takePhoto(launchSelf)
        }
        binding.btnNext.setOnClickListener {
            start(onNext = {
                showProgress()
                val map = getHttpMap()
                map["frontId"] = viewModel.frontId
                map["livingId"] = viewModel.livingId
                map["frontIdSuffix"] = "jpg"
                map["livingIdSuffix"] = "jpg"
                val similarity = getApiService().compare(map.sign(38)).result?.pass ?: false
                if (!similarity) {
                    toast("Selfie no coincide con la foto de identificación")
                    return@start
                }
                upload()
            }, onComplete = {
                dismissProgress()
            })
        }
    }

    private suspend fun upload() {
        Af.click_submit_personInfo.track(this)
        val map = getHttpMap()
        map["curp"] = binding.etIdNum.text.toString()
        map["father_surname"] = binding.etFatherName.text.toString()
        map["mother_surname"] = binding.etMotherName.text.toString()
        map["real_name"] = binding.etFirstName.text.toString()
        map["tax_id"] = binding.etRfcStart.text.toString() + binding.etRfcEnd.text.toString()
        map["frontId"] = viewModel.frontId
        map["reverseId"] = viewModel.reverseId
        map["livingId"] = viewModel.livingId
        map["frontIdSuffix"] = "jpg"
        map["reverseIdSuffix"] = "jpg"
        map["livingIdSuffix"] = "jpg"
        viewModel.uploadInfo(map)
    }

    override fun updateBtn() {
        binding.btnNext.isEnabled = views.all { it.text.isNotBlank() && viewModel.frontId.isNotBlank() && viewModel.reverseId.isNotBlank() && viewModel.livingId.isNotBlank() }
    }

    private fun toGallery(launcher: ActivityResultLauncher<Intent>) {
        start(onNext = {
            val granted = RxPermissions(this).request(Manifest.permission.READ_EXTERNAL_STORAGE).awaitFirst()
            if (granted) {
                val intent = Intent(Intent.ACTION_PICK)
                intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*")
                launcher.launch(intent)
            }
        })
    }


    private fun takePhoto(launcher: ActivityResultLauncher<Intent>) {
        RxPermissions(this)
            .request(Manifest.permission.CAMERA)
            .getResponse(this, {
                if (it) {
                    externalCacheDir?.apply {
                        val path = path + "/" + System.currentTimeMillis() + ".jpg"
                        if (launcher == launchFrontByCamera) viewModel.frontPath = path else if (launcher == launchReverseByCamera) viewModel.reversePath = path else viewModel.livingPath = path
                        val file = File(path)
                        val uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                            FileProvider.getUriForFile(this@InfoPersonActivity, packageName, file)
                        } else {
                            Uri.fromFile(file)
                        }
                        val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
                        intent.putExtra(MediaStore.EXTRA_OUTPUT, uri)
                        launcher.launch(intent)
                    }
                }
            })
    }
}